/*
 * Windows has cdecl, stdcall and fastcall calling convention:
 * +----------+------------+-------------------+-----------+
 * |          | stack      | scratch registers | parameter |
 * |          | cleanup by | (saved by caller) | registers |
 * +----------+------------+-------------------+-----------+
 * | cdecl    | caller     | eax, ecx, edx     |           |
 * +----------+------------+-------------------+-----------+
 * | stdcall  | callee     | eax, ecx, edx     |           |
 * +----------+------------+-------------------+-----------+
 * | fastcall | callee     | eax               | ecx, edx  |
 * +----------+------------+-------------------+-----------+
 */
#include <stdio.h>


int add1(int a, int b)
{
    return a + b;
}

/* equivalent to add1() */
int add2(int a, int b)
{
    __asm {
        mov eax, a;
        add eax, b;
    }
}

/* equivalent to add1(), use ebx */
/* an additional instruction to save ebx is added. */
int add3(int a, int b)
{
    __asm {
        mov ebx, a;
        add ebx, b;
        mov eax, ebx;
    }
}

/* equivalent to add1(), use stdcall */
int __stdcall add4(int a, int b)
{
    __asm {
        mov eax, a;
        add eax, b;
    }
}

/* equivalent to add1(), use fastcall */
int __fastcall add5(int a, int b)
{
    __asm {
        mov eax, a;
        add eax, b;
    }
}

/* equivalent to add1(), use __declspec(naked) to write our own prolog/epilog code sequences */
__declspec(naked) int __cdecl add6(int a, int b)
{
    __asm {
        push ebp;
        mov ebp, esp;
        mov eax, a;
        add eax, b;
        pop ebp;
        ret;
    }
}

int main()
{
    int ret;
    ret = add1(1, 2);
    printf("ret1=%d\n", ret);
    ret = add2(3, 4);
    printf("ret2=%d\n", ret);
    ret = add3(5, 6);
    printf("ret3=%d\n", ret);
    ret = add4(7, 8);
    printf("ret4=%d\n", ret);
    ret = add5(9, 10);
    printf("ret5=%d\n", ret);
    ret = add6(11, 12);
    printf("ret6=%d\n", ret);
    return 0;
}

